package com.etong.citymap.connect;


import com.etong.citymap.module.Image;
import com.etong.citymap.util.log.LogDetailUtil;
import com.etong.citymap.util.log.LogUtil;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 文件名称：UploadImage.java
 *
 * 版权信息：杭州电子科技大学 TD 实验室
 * 
 * 功能描述：
 * 
 * 创建日期：2011-5-10
 *
 * 作者：Huagang Li
 */

/*
 * 实现图片文件上传
 * 修改历史：
 */
public class UploadImage {
	String multipart_form_data = "multipart/form-data";
	String twoHyphens = "--";
	String boundary = "---------------------------7da2137580612";	// 数据分隔符
	String lineEnd = System.getProperty("line.separator");	// The value is "\r\n" in Windows.
	final String endline = "--" + boundary + "--\r\n";//数据结束标志  

	/*
	 * 上传图片内容，格式请参考HTTP 协议格式。
	 * 人人网Photos.upload中的”程序调用“http://wiki.dev.renren.com/wiki/Photos.upload#.E7.A8.8B.E5.BA.8F.E8.B0.83.E7.94.A8
	 * 对其格式解释的非常清晰。
	 * 格式如下所示：
	 * --****************fD4fH3hK7aI6
	 * Content-Disposition: form-data; name="upload_file"; filename="apple.jpg"
	 * Content-Type: image/jpeg
	 * 
	 * 这儿是文件的内容，二进制流的形式
	 */
	private void addImageContent(Image[] files, DataOutputStream output) {
		for(Image file : files) {
			StringBuilder split = new StringBuilder();
			split.append(twoHyphens + boundary + lineEnd);
			split.append("Content-Disposition: form-data; name=\"" + file.getFormName() + "\"; filename=\"" + file.getFileName() + "\"" + lineEnd);
			split.append("Content-Type: " + file.getContentType() + lineEnd);
			split.append(lineEnd);
			try {
				// 发送图片数据
				output.writeBytes(split.toString());
				output.write(file.getData(), 0, file.getData().length);
				output.writeBytes(lineEnd);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		
	}

	/*
	 * 构建表单字段内容，格式请参考HTTP 协议格式（用FireBug可以抓取到相关数据）。(以便上传表单相对应的参数值)
	 * 格式如下所示：
	 * --****************fD4fH3hK7aI6
	 * Content-Disposition: form-data; name="action"
	 * // 一空行，必须有
	 * upload 
	 */
	private void addFormField(Map<Object,Object> params, DataOutputStream output) {
		StringBuilder sb = new StringBuilder();

		try {
			for(Object param : params.keySet()) {
				sb.append(twoHyphens + boundary + lineEnd);
				sb.append("Content-Disposition: form-data; name=\"" + param + "\"" + lineEnd);
				sb.append(lineEnd);
				sb.append(URLEncoder.encode(params.get(param)==null?"":params.get(param).toString(), "utf-8") + lineEnd);
				
			}
			LogDetailUtil.i("上传案卷的参数数据信息=" + sb);
			output.writeBytes(sb.toString());// 发送表单字段数据
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 直接通过 HTTP 协议提交数据到服务器，实现表单提交功能。
	 * @param actionUrl 上传路径
	 * @param params 请求参数key为参数名，value为参数值
	 * @param files 上传文件信息
	 * @return 返回请求结果
	 */
	public String post(String actionUrl, Map<Object,Object> params, Image[] files) {
		HttpURLConnection conn = null;
		DataOutputStream output = null;
		BufferedReader input = null;
		try {
			LogDetailUtil.i("上传案卷的URL信息=" + actionUrl);
			URL url = new URL(actionUrl);
			conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(120000);
			conn.setDoInput(true);		// 允许输入
			conn.setDoOutput(true);		// 允许输出
			conn.setUseCaches(false);	// 不使用Cache
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Connection", "keep-alive");
			conn.setRequestProperty("Content-Type", multipart_form_data + "; boundary=" + boundary);

			conn.connect();
			output = new DataOutputStream(conn.getOutputStream());

			addImageContent(files, output);	// 添加图片内容

			addFormField(params, output);	// 添加表单字段内容
			output.write(endline.getBytes());  
			//output.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);// 数据结束标志
			output.flush();
			//			output.close();

			int code = conn.getResponseCode();
			if(code != 200) {
				throw new RuntimeException("请求‘" + actionUrl +"’失败！");
			}

			input = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			StringBuilder response = new StringBuilder();
			String oneLine;
			while((oneLine = input.readLine()) != null) {
				response.append(oneLine);
			}
			//			input.close();

			String returnValue = response.toString();
			LogDetailUtil.i("上传案卷的返回信息=" + returnValue);
			return returnValue;
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			// 统一释放资源
			try {
				if(output != null) {
					output.close();
				}
				if(input != null) {
					input.close();
				}
			} catch (IOException e) {
				throw new RuntimeException(e);
			}

			if(conn != null) {
				conn.disconnect();
			}
		}
	}

   public static String post( String actionUrl ,  
          Map < String , String > params , Map < String , File > files )  
                throws IOException  
       {  
 
                String BOUNDARY = java.util.UUID.randomUUID ( ).toString ( ) ;  
                String PREFIX = "--" , LINEND = "\r\n" ;  
                String MULTIPART_FROM_DATA = "multipart/form-data" ;  
                String CHARSET = "UTF-8" ;  
  
               URL uri = new URL ( actionUrl ) ;  
               HttpURLConnection conn = ( HttpURLConnection ) uri .openConnection ( ) ;  
                conn.setReadTimeout ( 5 * 1000 ) ; // 缓存的最长时间  
            conn.setDoInput ( true ) ;// 允许输入  
            conn.setDoOutput ( true ) ;// 允许输出  
            conn.setUseCaches ( false ) ; // 不允许使用缓存  
            conn.setRequestMethod ( "POST" ) ;  
            conn.setRequestProperty ( "connection" , "keep-alive" ) ;  
            conn.setRequestProperty ( "Charsert" , "UTF-8" ) ;  
            conn.setRequestProperty ( "Content-Type" , MULTIPART_FROM_DATA  
                    + ";boundary=" + BOUNDARY ) ;  
  
                // 首先组拼文本类型的参数  
            StringBuilder sb = new StringBuilder ( ) ;  
            for ( Map.Entry < String , String > entry : params.entrySet ( ) )  
                {  
                    sb.append ( PREFIX ) ;  
                    sb.append ( BOUNDARY ) ;  
                   sb.append ( LINEND ) ;  
                    sb.append ( "Content-Disposition: form-data; name=\""  
                            + entry.getKey ( ) + "\"" + LINEND ) ;  
                   sb.append ( "Content-Type: text/plain; charset="  
                            + CHARSET + LINEND ) ;  
                   sb.append ( "Content-Transfer-Encoding: 8bit" + LINEND ) ;  
                        sb.append ( LINEND ) ;  
                        sb.append ( entry.getValue ( ) ) ;  
                        sb.append ( LINEND ) ;  
                    }  
 
                DataOutputStream outStream = new DataOutputStream (  
                        conn.getOutputStream ( ) ) ;  
                outStream.write ( sb.toString ( ).getBytes ( ) ) ;  
                // 发送文件数据  
            if ( files != null )  
                for ( Map.Entry < String , File > file : files.entrySet ( ) )  
                    {  
                        StringBuilder sb1 = new StringBuilder ( ) ;  
                        sb1.append ( PREFIX ) ;  
                        sb1.append ( BOUNDARY ) ;  
                        sb1.append ( LINEND ) ;  
                       sb1.append ( "Content-Disposition: form-data; name=\"file\"; filename=\""  
                                + file.getKey ( ) + "\"" + LINEND ) ;  
                        sb1.append ( "Content-Type: application/octet-stream; charset="  
                                    + CHARSET + LINEND ) ;  
                           sb1.append ( LINEND ) ;  
                            outStream.write ( sb1.toString ( ).getBytes ( ) ) ;  
  
                            InputStream is = new FileInputStream (  
                                    file.getValue ( ) ) ;  
                            byte [ ] buffer = new byte [ 1024 ] ;  
                            int len = 0 ;  
                           while ( ( len = is.read ( buffer ) ) != - 1 )  
                                {  
                                    outStream.write ( buffer , 0 , len ) ;  
                                }  
  
                            is.close ( ) ;  
                            outStream.write ( LINEND.getBytes ( ) ) ;  
                        }  
  
                // 请求结束标志  
            byte [ ] end_data = ( PREFIX + BOUNDARY + PREFIX + LINEND )  
                    .getBytes ( ) ;  
            outStream.write ( end_data ) ;  
            outStream.flush ( ) ;  
            // 得到响应码  
                int res = conn.getResponseCode ( ) ;  
                InputStream in = conn.getInputStream ( ) ;  
                if ( res == 200 )  
                    {  
                        int ch ;  
                        StringBuilder sb2 = new StringBuilder ( ) ;  
                        while ( ( ch = in.read ( ) ) != - 1 )  
                            {  
                               sb2.append ( ( char ) ch ) ;  
                            }  
                    }  
                outStream.close ( ) ;  
                conn.disconnect ( ) ;  
                return in.toString ( ) ;  
                  
            }  

	public static void main(String[] args) {
		try {
			String response = "";

			Image[] files = new Image[2];
			Image file = new Image("D:/e.js", "a1");
			files[0] = file;
			Image file1 = new Image("D:/excel_errlog.txt", "a1");

			files[1] = file1;

			Map<Object,Object> map = new HashMap<Object, Object>();
			map.put("uploadfilename", "测试的文件");
			response = new UploadImage().post("http://192.168.10.165:8080/udm/mobile!fileUpload.c", map, files);
			System.out.println("返回结果：" + response);
		} catch (Exception e) {
			LogUtil.e(e);
		}
	}
}
